﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Apex.EventBus.EventBuses
{
    /// <summary>
    /// 管理事件订阅关系的类
    /// </summary>
    class SubscriptionsManager
    {
        // 存储事件名称和对应监听该事件的处理程序类型的字典
        private readonly Dictionary<string, List<Type>> _handlers = new Dictionary<string, List<Type>>();

        /// <summary>
        /// 当事件移除时触发的事件
        /// </summary>
        public event EventHandler<string> OnEventRemoved;

        /// <summary>
        /// 获取是否没有任何事件订阅
        /// </summary>
        public bool IsEmpty => !_handlers.Keys.Any();

        /// <summary>
        /// 清空所有订阅关系。
        /// </summary>
        public void Clear() => _handlers.Clear();

        /// <summary>
        /// 将实现了指定事件处理程序类型的类注册为监听了指定事件
        /// </summary>
        /// <param name="eventName">事件名称</param>
        /// <param name="eventHandlerType">事件处理程序类型</param>
        public void AddSubscription(string eventName, Type eventHandlerType)
        {
            // 如果尚未有任何事件的订阅关系，则添加一个新的事件列表
            if (!HasSubscriptionsForEvent(eventName))
            {
                _handlers.Add(eventName, new List<Type>());
            }

            // 如果该事件已经被注册，则抛出异常
            if (_handlers[eventName].Contains(eventHandlerType))
            {
                throw new ArgumentException($"Handler Type {eventHandlerType} already registered for '{eventName}'", nameof(eventHandlerType));
            }

            // 添加事件处理程序类型到事件列表中
            _handlers[eventName].Add(eventHandlerType);
        }

        /// <summary>
        /// 移除对指定事件的订阅
        /// </summary>
        /// <param name="eventName">事件名称</param>
        /// <param name="handlerType">要移除的事件处理程序类型</param>
        public void RemoveSubscription(string eventName, Type handlerType)
        {
            // 移除指定类型的事件处理程序
            _handlers[eventName].Remove(handlerType);

            // 如果该事件已经没有任何订阅，则移除事件，并触发事件移除事件
            if (!_handlers[eventName].Any())
            {
                _handlers.Remove(eventName);
                OnEventRemoved?.Invoke(this, eventName);
            }
        }

        /// <summary>
        /// 获取监听指定事件的所有处理程序类型
        /// </summary>
        /// <param name="eventName">事件名称</param>
        /// <returns>监听该事件的处理程序类型的枚举</returns>
        public IEnumerable<Type> GetHandlersForEvent(string eventName) => _handlers[eventName];

        /// <summary>
        /// 检查是否有任何类型监听指定事件
        /// </summary>
        /// <param name="eventName">事件名称</param>
        /// <returns>如果有任何类型监听指定事件，则为true；否则为false</returns>
        public bool HasSubscriptionsForEvent(string eventName) => _handlers.ContainsKey(eventName);
    }
}
